package com.aldobucchi.mouse
{

	import flash.events.Event;
	
	import com.aldobucchi.core.dependency.DependencySpec;
	import com.aldobucchi.utils.App;


	/**
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */
	public class MouseNavigationTracker extends MouseTrackerBase
	{


		public static const marginSizeChanged:String = "marginSizeChanged";


		
		private var hoverTracker:MouseHoverTracker;


		
		///////////////////////////////////////////
		// marginSize
		///////////////////////////////////////////

		private var marginSizeSpec:DependencySpec = new DependencySpec( "marginSize", marginSizeChanged, null, false, 0.2 );
		
		[Bindable( marginSizeChanged )]
		/**
		 * 
		 * The margin ( fraction of the target size ).
		 * A value of 0.1 over a 100px width rectangle will create a margin of 10px on each side
		 * 
		 * @return 
		 * 
		 */		
		public function get marginSize( ):Number
		{
			return dh.getDependencyValue( marginSizeSpec );
		}
		
		public function set marginSize( v:Number ):void
		{
			dh.setDependencyValue( marginSizeSpec, v );
		}

		


		///////////////////////////////////////////
		// navX
		///////////////////////////////////////////

		private var _navX:Number;
		[Bindable( "change" )]
		public function get navX( ):Number
		{
			return _navX;
		}


		///////////////////////////////////////////
		// navY
		///////////////////////////////////////////

		private var _navY:Number;
		[Bindable( "change" )]
		public function get navY( ):Number
		{
			return _navY;
		}


		



		///////////////////////////////////////////
		// etc...
		///////////////////////////////////////////


		/**
		* Recalculated every time the target is set
		*/
		private var xMarks:Array;
		
		private var yMarks:Array;




		
		///////////////////////////////////////////
		// constructor
		///////////////////////////////////////////
		
		
		public function MouseNavigationTracker( )
		{
		
			hoverTracker = new MouseHoverTracker( );
			hoverTracker.strategy = MouseHoverTracker.STRATEGY_WH; // the broadest strategy			
			
			App.app.addEventListener( Event.ENTER_FRAME, onEnterFrame, false, 0, true );
			
		
		}




		private function onEnterFrame( event:Event ):void
		{
			
			updateCoords( );
					
		}





		override protected function dependenciesUpdated( ):void
		{
			
			super.dependenciesUpdated( );
			
			
			if ( dh.modifications[ targetSpec ] )
			{

				hoverTracker.target = target;
				calculateMarks( );

			}
			
			
			if ( enabled == false || !target )
			{
				setNewNavValues( 0, 0 );
				return;		
			}
			
			
			updateCoords( );

		}

		
		
		
		private function calculateMarks( ):void
		{
			
			if ( ! target )
				return;			
			
			// TODO: should we consider scaling??
			var marginX:int = target.width * marginSize;
			var marginY:int = target.height * marginSize;
			
			xMarks = [ marginX, target.width - marginX ];						
			yMarks = [ marginY, target.height - marginY ];						
		
		}
		
		

		
		
		
		
		private function updateCoords( ):void
		{
			
			if ( ! target || !hoverTracker.hover )
			{
				setNewNavValues( 0, 0 );
				return;
			}
			
			
			// KLUDGE:
			// need to do this every time because we might not know
			// the target's height and width on injection time
			calculateMarks( );
			// this has to be fixed
			

			var diffX:Number = 0;
			var diffY:Number = 0;

			var x:int = target.mouseX;
			var y:int = target.mouseY;
			
			
			if ( x < xMarks[ 0 ] )
				diffX = x - xMarks[ 0 ];				
			else if ( x > xMarks[ 1 ] )
				diffX = x - xMarks[ 1 ];

			
			if ( y < yMarks[ 0 ] )
				diffY = y - yMarks[ 0 ];				
			else if ( y > yMarks[ 1 ] )
				diffY = y - yMarks[ 1 ];				
			

			setNewNavValues(  diffX / xMarks[0] , diffY / yMarks[0] );
		
		}



		private function setNewNavValues( x:Number, y:Number ):void
		{
			
			if ( !isFinite( x ) || !isFinite( y ) )
			{ // this happens when the target width is zero
				x = 0;
				y = 0;	
			}					
			
			var changed:Boolean = false;
			
			if ( _navX != x )
			{
				_navX = x;
				changed = true;
			}
			
			if ( _navY != y )
			{
				_navY = y;
				changed = true;
			}

			if ( changed )
			{
				dispatchEvent( new Event( Event.CHANGE ) );
			}
		
		}





		
	}


}